﻿package com.bizmlib.framework.abstract
{
	/**
	 * Is the main class for the site. It handles the site loading and creates instances of model, view and controller.
	 * @author	Valentyn Derkach
	 */
	
	import com.bizmlib.framework.abstract.mvc.*;
	
	
	public class AbstractEngine extends Object
	{
		private static var STATE_INIT:Number = 1;
		private static var STATE_STARTEDUP:Number = STATE_RUNNING;
		private static var STATE_RUNNING:Number = 2;
	
		private static var __instance:AbstractEngine;
	
		private var state:Number = STATE_INIT;
		private var __model:AbstractModel;
		private var __view:AbstractView;
		private var __controller:AbstractController;
		
		
		public function AbstractEngine()
		{
			//trace("SiteEngneBase(" + arguments + ")");
	
			checkInstance();
	
			__instance = this;
			//trace("__instance=" + __instance + "\tinstance=" + instance);
	
			init();
		}
	
	
		/**
		 * Returns a single instance of the class. Read-only.
		 * It is better if you override this method in your subclass, in order to make it work.
		 */
		public static function get instance():AbstractEngine
		{
			//trace("AbstractEngine.instance (get)");
			//trace("__instance=" + __instance);
			return __instance;
		}
		/**
		 * Getter of the model, view and controller properties
		 */
		public function get model():AbstractModel{return __model;}
		public function get view():AbstractView{return __view;}
		public function get controller():AbstractController{return __controller;}
	
	
	
		/**
		 * Starts up the engine.
		 */
		public function startUp(modelInstance:AbstractModel = undefined, viewInstance:AbstractView = undefined, controllerInstance:AbstractController = undefined):Boolean
		{
			//trace(this + ".startUp(" + arguments + ")");
			//trace("checkInitValues()=" + checkInitValues());
	
			if(!checkInitValues())
			{
				return false;
			}
	
			try
			{
				createMVCInstances(modelInstance, viewInstance, controllerInstance);
				state = STATE_RUNNING;
				afterStartUp();
			}
			catch(error:Error)
			{
				//trace(error + newline + "Some serious error has occured. Execution was terminated.");
				return false;
			}
	
			return true;
		}
	
	
		/**
		 * Invoked from the constructor. Currently is empty. Feel free to override.
		 */
		private function init():void
		{
			//trace(this + ".init(" + arguments + ")");
		}
	
		/**
		 * This method is invoked from withing the startUp method and it is checking if all the properties required for the start up process are properly initialized.
		 * @return	true in case engine was properly initialized.
		 */
		private function checkInitValues():Boolean
		{
			return true;
		}
	
		private function checkInstance():Boolean
		{
			if(instance)
			{
				throw new Error(AbstractEngine + " constructor failed: only one instance of AbstractEngine or any of its decendant class can be created.");
				return false;
			}
			else
			{
				return true;
			}
		}
	
	
		private function createMVCInstances(modelInstance:AbstractModel, viewInstance:AbstractView, controllerInstance:AbstractController):Boolean
		{
			//trace(this + ".createMVCInstances(" + arguments + ")");
	
			createModel(modelInstance);
			//trace("createView=" + createView);
			createView(viewInstance);
			//trace("createController=" + createController);
			createController(controllerInstance);
	
			return true;
		}
		protected function createModel(modelInstance:AbstractModel):void
		{
			//trace(this + ".createModel(" + arguments + ")");
			__model = modelInstance || (new AbstractModel());
		}
		protected function createView(viewInstance:AbstractView):void
		{
			//trace(this + ".createView(" + arguments + ")");
			__view = viewInstance || (new AbstractView(/**/model/**undefined/**/));
		}
		protected function createController(controllerInstance:AbstractController):void
		{
			//trace(this + ".createController(" + arguments + ")");
			__controller = controllerInstance || (new AbstractController(view));
		}
		/**
		 * Invoked from the startUp method when the engine is successfully started up. Feel free to override.
		 */
		protected function afterStartUp():void
		{
		}
	
	
		/**
		 * Returns a strng describing the instance.
		 */
		public function toString():String
		{
			return "[com.bizmlib.framework.abstract.AbstractEngine]";
		}
	}
}